package hello;

import java.util.List;

import org.hibernate.CacheMode;
import org.hibernate.Filter;
import org.hibernate.Query;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
import org.hibernate.engine.FilterDefinition;

import persistence.HibernateUtil;
import auction.chapter05.model.CreditCard_Join;
import auction.chapter05.model.CreditCard_SingleTable;
import auction.chapter05.model.CreditCard_Union;
import auction.chapter10.ItemVersion;
import auction.chapter12.AuditLogInterceptor;

/**
 * Chapter 12
 * @author wei
 *
 */
public class HelloWorldBulkBatch
{
	private static int batch_size=5;
	
	public static void main(String[] args)throws Exception{
	    //bulkUpdate_SingleTable();
	    //bulkUpdate_union();
	    //bulkUpdate_join();
	    //bulkUpdate_join_parent();
		bulkUpdate();
		//bulkInsert();
		
		//batchUpdate();
		//statelessSessionUpdate();
		
		//dataFilter();
	    //interceptor();
	}
	
	public static void interceptor()throws Exception{
		AuditLogInterceptor inter=new AuditLogInterceptor();
		//Open session on a Interceptor
		Session s=HibernateUtil.getSessionFactory().openSession(inter);
		Transaction tx=s.beginTransaction();
		
		inter.setSession(s);
		inter.setUserId(123L);
		
		Message2 msg=new Message2();
		msg.setText("abc");
		
		s.save(msg);
		
		tx.commit();
		s.close();
		
		////
		Session s2=HibernateUtil.getSessionFactory().openSession(inter);
        Transaction tx2=s2.beginTransaction();
        
        inter.setSession(s2);
        inter.setUserId(465L);
        /*
        Message2 loadmsg=(Message2)s2.load(Message2.class, 1L);
        loadmsg.setText("def");
        s2.update(loadmsg);
        */
        tx2.commit();
        s2.close();
	}
	
	public static void dataFilter()throws Exception{
		//enable the filter
		Session s=HibernateUtil.getSessionFactory().openSession();
		Filter filter=s.enableFilter("filterByRank");
		filter.setParameter("currentRank", 5);
		filter.validate();
		
		FilterDefinition fdef=filter.getFilterDefinition();
		out(fdef.getDefaultFilterCondition());
		out(fdef.getFilterName());
		out(fdef.getParameterNames());
		out(fdef.getParameterTypes());
		
		Transaction tx=s.beginTransaction();
		
		List<Message2> l=s.createQuery("from Message2").list();
		for(Message2 m : l){
			out(m.getText()+" "+m.getRank());
		}
		
		tx.commit();
		s.close();
	}
	
	public static void statelessSessionUpdate()throws Exception{
		StatelessSession s=HibernateUtil.getSessionFactory().openStatelessSession();
		Transaction tx=s.beginTransaction();
		
		ScrollableResults cursor=s.createQuery("from Message2").scroll();
		
		while(cursor.next()){
			Message2 msg=(Message2)cursor.get(0);//only return current result row
			msg.setText("stateless session update");
			s.update(msg);//one update SQL
			out("one update loop");
		}
		
		tx.commit();
		s.close();
	}
	
	public static void batchUpdate()throws Exception{
		Session s=HibernateUtil.getSessionFactory().openSession();
		Transaction tx=s.beginTransaction();
		
		ScrollableResults cursor=s.createQuery("from Message2").scroll();
		int count=0;
		while(cursor.next()){//move cursor to next
			Message2 msg=(Message2) cursor.get(0);//return this result
			msg.setText("batch updated");
			if(++count % batch_size ==0){
				out("enter one batch");
				s.flush();
				s.clear();
			}
		}
		
		tx.commit();
		s.close();
	}
	
	public static void batchInsert()throws Exception{
		Session s=HibernateUtil.getSessionFactory().openSession();
		Transaction tx=s.beginTransaction();
		
		//never interact with second-level cache
		s.setCacheMode(CacheMode.IGNORE);
		
		for(int i=0;i<100000;i++){
			Message2 msg=new Message2();
			s.save(msg);
			if(i % batch_size == 0){
				s.flush();
				s.clear();
			}
		}
		
		tx.commit();
		s.close();
	}
	
	public static void bulkInsert()throws Exception{
		Session s=HibernateUtil.getSessionFactory().openSession();
		Transaction tx=s.beginTransaction();
		
		Query q=s.createQuery("insert into ItemVersion(title) " +
								"select text from Message2");
		out(q.executeUpdate());
		
		tx.commit();
		s.close();
	}
	
	public static void bulkUpdate()throws Exception
	{
		
		Session s=HibernateUtil.getSessionFactory().openSession();
		Transaction tx=s.beginTransaction();

		Message2 m1=new Message2();
		m1.setText("first");
		
		Message2 m2=new Message2();
		m2.setText("second");
		/*
		ItemVersion iv=new ItemVersion();
		iv.setCode("ok");
		*/
		s.save(m1);
		s.save(m2);
		//s.save(iv);
		
		tx.commit();
		s.close();
		
		
		
		Session s1=HibernateUtil.getSessionFactory().openSession();
		Transaction tx1=s1.beginTransaction();
		
		/* ========== update first then execute get entity will get fresh data 
		Query q=s1.createQuery("update Message2 m set text = :a");
		q.setString("a","yi guan miao b");
		out(q.executeUpdate());
		
		Message2 afterquery=(Message2)s1.get(Message2.class, m1.getId());
		out("afterquery after update:"+afterquery.getText());//output new data
		*/
		
		/* ========== get first - bulk update - get - refresh  =========== */
		Message2 beforequery=(Message2)s1.get(Message2.class, m1.getId());
		out("beforequery"+beforequery+" before update:"+beforequery.getText());//output old data
		
		//bypass first level cache
		Query q=s1.createQuery("update Message2 m set text = :a");
		q.setString("a","yi guan miao b");
		out(q.executeUpdate());
		
		Message2 afterquery=(Message2)s1.get(Message2.class, m1.getId());//session guarantee identity
		out("afterquery  "+afterquery+" after update:"+afterquery.getText());//output old data
		out("beforequery "+beforequery+" after update:"+beforequery.getText());//output old data
		
		s1.refresh(afterquery);
		out("afterquery  "+afterquery+" after refresh:"+afterquery.getText());//the same object,output NEW data

		/*
		Query q2=s1.createQuery("update versioned ItemVersion set title = :a");
		q2.setString("a","title");
		out(q2.executeUpdate());
		*/
		
		
		tx1.commit();
		s1.close();
		
		
		HibernateUtil.shutdown();
	}
	
	public static void bulkUpdate_SingleTable()throws Exception
    {
        
        Session s=HibernateUtil.getSessionFactory().openSession();
        Transaction tx=s.beginTransaction();

        CreditCard_SingleTable ccs=new CreditCard_SingleTable();
        ccs.setOwner("wei");
        ccs.setNumber("4111111");
        s.save(ccs);
        
        tx.commit();
        s.close();
        
        
        
        Session s1=HibernateUtil.getSessionFactory().openSession();
        Transaction tx1=s1.beginTransaction();
        
        /* update billingdetails_singletable set owner=? where billing_details_type='CC' */
        Query q=s1.createQuery("update CreditCard_SingleTable m set owner = :a");
        q.setString("a","yi guan miao b");
        out(q.executeUpdate());
        
        
        tx1.commit();
        s1.close();
        
        
        HibernateUtil.shutdown();
    }
	
	public static void bulkUpdate_union()throws Exception
    {
        
        Session s=HibernateUtil.getSessionFactory().openSession();
        Transaction tx=s.beginTransaction();

        CreditCard_Union ccs=new CreditCard_Union();
        ccs.setOwner("wei");
        ccs.setNumber("4111111");
        s.save(ccs);
        
        tx.commit();
        s.close();
        
        
        
        Session s1=HibernateUtil.getSessionFactory().openSession();
        Transaction tx1=s1.beginTransaction();
        
        /* update creditcard_union set owner=? */
        Query q=s1.createQuery("update CreditCard_Union m set owner = :a");
        q.setString("a","yi guan miao b");
        out(q.executeUpdate());
        
        
        tx1.commit();
        s1.close();
        
        
        HibernateUtil.shutdown();
    }
	
	public static void bulkUpdate_join()throws Exception
    {
        
        Session s=HibernateUtil.getSessionFactory().openSession();
        Transaction tx=s.beginTransaction();

        CreditCard_Join ccs=new CreditCard_Join();
        ccs.setOwner("wei");
        ccs.setNumber("4111111");
        s.save(ccs);
        
        tx.commit();
        s.close();
        
        
        
        Session s1=HibernateUtil.getSessionFactory().openSession();
        Transaction tx1=s1.beginTransaction();
        /*
           insert 
    into
        HT_creditcard_join
        select
            creditcard0_.credit_card_id as credit_card_id 
        from
            creditcard_join creditcard0_ 
        inner join
            billingdetails_join creditcard0_1_ 
                on creditcard0_.credit_card_id=creditcard0_1_.billing_details_id

    update
        creditcard_join 
    set
        number=? 
    where
        (
            credit_card_id
        ) IN (
            select
                credit_card_id 
            from
                HT_creditcard_join
        )
        */
        Query q=s1.createQuery("update CreditCard_Join m set number = :a");
        q.setString("a","4111111111111111");
        out(q.executeUpdate());
        
        
        tx1.commit();
        s1.close();
        
        
        HibernateUtil.shutdown();
    }
	
	public static void bulkUpdate_join_parent()throws Exception
    {
        
        Session s=HibernateUtil.getSessionFactory().openSession();
        Transaction tx=s.beginTransaction();

        CreditCard_Join ccs=new CreditCard_Join();
        ccs.setOwner("wei");
        ccs.setNumber("4111111");
        s.save(ccs);
        
        tx.commit();
        s.close();
        
        
        
        Session s1=HibernateUtil.getSessionFactory().openSession();
        Transaction tx1=s1.beginTransaction();
        /*
           insert into
              HT_billingdetails_join
           select
            billingdet0_.billing_details_id as billing_details_id 
           from
            billingdetails_join billingdet0_

        update
          billingdetails_join 
        set
          owner=? 
        where
        (
            billing_details_id
        ) IN (
            select
                billing_details_id 
            from
                HT_billingdetails_join
        )
        */
        Query q=s1.createQuery("update BillingDetails_Join m set owner = :a");
        q.setString("a","yi guan miao b");
        out(q.executeUpdate());
        
        tx1.commit();
        s1.close();
        
        
        HibernateUtil.shutdown();
    }
	
	public static void getParent(Class clazz)
	{
		Class parent=clazz.getSuperclass();
	  if(parent !=null)
	  {
			System.out.println("###"+parent.getName());
			getParent(parent);
		}
	}
	
	static void out(Object obj)
	{
		System.out.println("--->" + obj);
	}
}
